Résumé

This workshop is an introduction to Google Earth Engine (GEE).

Earth Engine is an online software from Google that allow users to manipulate and analyze lots of geographical layers (satellite imagery, climate data, topographic layers, etc.). An advantage to use GEE is that most of the calculation are done online on Google cloud and not on a personnal computer. The following manupulations are an introduction to GEE tools with coding chunks that are easy to reproduce and to adapt to users needs.

Objectives

Step 1: Interface overview

First you need to have a Google account if to access GEE plateform. You can sign up to GEE with your Gmail identifiant to the following link.https://signup.earthengine.google.com/#!/. Once you registrer to GEE, you can access the code editor to this link: https://code.earthengine.google.com/.

Here are some information about the interface.

Left Pannel

Center Pannel

Right Pannel

Search Bar

Map

Step 2: Select a region of interest with geometry tools

Start by navigatiting to La Mauricie National Park. You can search “Shawinigan” in the search bar to help you to locate the place.

  1. With the geometry tool, add a landmark by clicking on the landmark pictogram and put a points in the middle of the National Park.
  2. Click on “Exit” once the landmark is in place to avoid adding other points.
  3. Rename the landmark “pnm” in the script.

An alternative to geometry tools is to type this code to place a landmark. To complete the landmark you would have to click on the import option given by the code after typing it.

var pnm = /* color: #d63000 */ee.Geometry.Point([-72.97, 46.74])

Do not forget to save you script with the Save button.

Step 3: Load and display elevation layer

To import a dataset, you have to import it from Earth Engine database. To do so, you can use the search bar to search for the dataset needed. Once it is imported, the dataset will not be displayed automatically. You will have to define visualization parameters and boundaries around where you want to display the dataset, otherwise it will display the dataset for all its area.

// Print information from the dataset in the right console
print(srtm);
// Display the elevation layer
Map.addLayer(srtm);

// Give a range of value to display the elevation layer
Map.addLayer(srtm, {min: 0, max: 400},"Elevation");
// Add elevation layer with visualisation parameter to create a nice map
Map.addLayer(srtm, {min: 0, max: 400, palette: ['blue', 'yellow', 'red']},"Elevation with colour");

// Create a hillshade layer 
var hillshade = ee.Terrain.hillshade(srtm);

// Display hillshade map
Map.addLayer(hillshade, {min: 150, max:255}, 'Hillshade');
// Create a slope layer
var slope = ee.Terrain.slope(srtm);

//Display slope map
Map.addLayer(slope, {min: 0, max: 30}, 'Slope');

Step 4 Work with sattelite imagery for a region of interest

Google Earth Engine dataset allow to work with tons of satellite images. To focus on a region of interest you will have to apply some filter. Begin by importing images from Sentinel 2 satellite. It would have been possible to work with Landsat images also.

-The following lines define some filter for the region of interest selected earlier in La Mauricie National Park between September and October 2020 and for the less cloudy image possible. You can also print the result of your query in the console with the function .size to get an idea of the number of images available depending of the filter you put.

// Create a variable for the satellite image
var pnm_s2=sent2
    .filterBounds(pnm) // Geographical filter
    .filterDate("2020-07-01", "2020-08-30") // Temporal filter
    .filterMetadata('CLOUDY_PIXEL_PERCENTAGE','less_than',10);// Filter for image clearness

// Query for number of picture corresponding to all filters
print(pnm_s2.size(),"n. images");
                              

Previous code allow to display many images at the same time. The next one will be preferred to select the best images according to filter applied.

// Create an object that contain the satellite image selected 
var pnm_i = sent2
    .filterBounds(pnm) // Geographical filter
    .filterDate("2020-07-01", "2020-09-30") // Temporal filter
    .sort("CLOUD_COVERAGE_ASSESSMENT") // Filter for image clearness
    .first(); // Select the less cloudy image 

print(pnm_i,"Best image");
      
//extra : 2nd best?
var pnm_i2 = sent2
    .filterDate("2020-07-01", "2020-09-30")
    .filterBounds(pnm)
    .sort("CLOUD_COVERAGE_ASSESSMENT")
    .select(1);  //first index is 0, so the 2nd best image will be selected by 1
print(pnm_i2, "2nd best image");
      
// Define visualization parameters
var rgb_colour = {
        bands: ["B4", "B3", "B2"],
        min: 0,
        max: 1850
        };

Map.addLayer(pnm_i,rgb_colour,"Sentinel-2 Image");

Step 5: Display a satellite image with the boundaries of a shapefile

In the previous step you worked with a landmark placed in the La Mauricie National Park. It would be also possible to import a shapefile to work in this selected area with Google Earth Engine. In this step you will have to import a shapefile associated to the National Park so display an image exclusively in this area.

 // Add a variable corresponding to a shapefile
var pnm_poly = ee.FeatureCollection('users/XXX/PNM_poly');
// Display satellite image for the shapefile area of the National Park
Map.addLayer(pnm_i.clip(shape_pnm),rgb_colour,"Satellite Image cropped");

Step 6: Calculate a spectral index (ex: NDVI)

Another exercise with Google Earth Engine is to create a new layer which contain a calculated band like NDVI index (Normalized difference vegetation index).

This type of index is often use to highlight some element of an existing image. In the case of NDVI, it is a ratio between reflectance of red and near infrared bands that allow to highlight presence of vegetation in an image. The formula to calculate NDVI is show here.

\[NDVI = \frac{NIR-RED}{NIR+RED} \] - There is different method to calculate this kind of layer.

  1. By using a function.
// Creating the function 
var ndvi = function (x) {
  var result=x.normalizedDifference(["B8", "B4"]).rename("NDVI"); 
  return x.addBands(result);
};

// Apply the function to an image
var ndvi1 = ndvi(pnm_i);

// Display the result
Map.addLayer(ndvi1, {bands:['NDVI'],min:0,max:1,palette:['red','yellow','green']},"NDVI Method1");
  1. By using an expression that calculate difference between bands.
// Create the expression to calculate
var ndvi2 = pnm_i.expression(
     "(NIR - RED) / (NIR + RED)",
    {
      RED: pnm_i.select("B4"),
      NIR: pnm_i.select("B8"),
 }).rename('NDVI'); // Give a name to the band you created

// Display the result
Map.addLayer(ndvi2, {min: 0, max: 1,palette:['cyan','green','orange'] }, "NDVI Method 2");

Step 7: Image classification with Google Earth Engine

This exercice is about image classification with GEE. The following code make a supervised classification of an image for different type of landscape. First you need to build a training dataset where landscapes are known. After you can reuse the training data to extend the analysis to a bigger scale.

// Merge polygons together
var classNames = forest.merge(agriculture).merge(water).merge(city);

print(classNames);

var bands = ['B2', 'B3', 'B4', 'B8']; // Define the bands to use for the classification

// Create the training dataset 
var training = pnm_i.select(bands).sampleRegions({
  collection: classNames,
  properties: ['landcover'],
  scale: 30
});

print(training, 'training dataset');
//The classification algorithm (Here we use .cart tool but there is others)
var classifier = ee.Classifier.cart().train({
  features: training,
  classProperty: 'landcover',
  inputProperties: bands
});

// Apply classification to "pnm_i" and display the result
var classification = pnm_i.select(bands).classify(classifier);
Map.addLayer(classification, {min: 0, max: 3, palette: ['green', 'yellow','blue','red']}, 'classification');

// Add other bands
var bands2 = ['B2', 'B3', 'B4', 'B8', 'NDVI']; // pour définir les bandes a utiliser

// Create a new training dataset with the new bands of ndvi1 object
var training2 = ndvi1.select(bands2).sampleRegions({
  collection: classNames,
  properties: ['landcover'],
  scale: 30
});


// Classification algorithm
var classifier2 = ee.Classifier.cart().train({
  features: training2,
  classProperty: 'landcover',
  inputProperties: bands2
});

// Apply classification to ndvi1 object and display the result
var classification2 = ndvi1.select(bands2).classify(classifier2);

Map.addLayer(classification2, {min: 0, max: 3, palette: ['green', 'yellow','blue','red']}, 'classification +ndvi');

Step 8: Export raster layer to Google Drive

It is possible to export the layer you created in GEE via Google Drive. From there you can continue to modify those layers in a GIS software for example. In this step, you will export only a small region of the classification because the entire image would be too heavy to export.

// Create an export zone with a buffer
var zone=zone.buffer(1500);
Map.addLayer(zone,rgb_colour,"Export zone");
//Export raster
Export.image.toDrive({
  image: classification,
  description: 'image_classified',
  scale: 10,
  region: zone
});

Step 9: Draw graph with GEE

GEE allow also to create different type of charts to look at the distribution of the data. In this step, you will take the elevation layer that you will clip to La Mauricie National Park to create a chart about height distribution in this area.

// Clip the elevation layer for the National Park
var elevation1= srtm.clip(shape_pnm);
print(elevation1,"Elevation 1");

// Check the result
Map.addLayer(elevation1, {min: 0, max: 400, palette: ['blue', 'yellow', 'red']},"Elevation colour pnm");
// Draw a graph and print it in the console
var Chart1 = ui.Chart.image.histogram(
    elevation1,shape_pnm,30);
print(Chart1);
// Set some visualisation option to improve the look of the graph
var options = {
  title: "Height frequency distribution for La Mauricie National Park",
  fontSize: 15,
  hAxis: {title: "Elevation (m)"},
  vAxis: {title: 'Frequency'},
  series: {
    0: {color: 'magenta'}
  }}; 

// Create the improved graph
var Chart2 = ui.Chart.image.histogram(
    elevation1,shape_pnm,30)
    .setSeriesNames(['Height'])
    .setOptions(options);
print(Chart2);

End of the workshop